#include "msgsender.h"

MsgSender::MsgSender(QObject *parent) :
    QObject(parent)
{
    connect(&m_socket, SIGNAL(connected()), this, SLOT(slot_connected()));
    connect(&m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slot_errorString()));
    connect(&m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
    qRegisterMetaType<VEHICLE*>("PVEHICLE");
}


quint8 getXor(const char *buffer, int nSize)
{
    if(nSize == 0 || buffer == NULL)
    {
        return 0;
    }
    quint8 nXor = 0x00;
    for(int i = 0;i < nSize; i++)
    {
        nXor ^= buffer[i];
    }
    return nXor;
}

void MsgSender::slot_connected()
{
    emit connected();
}

void MsgSender::slot_errorString()
{
    emit errorString(m_socket.errorString());
}

void MsgSender::connectToHost(const QString &sIp, int nPort)
{
    m_socket.connectToHost(sIp, nPort);
}

void MsgSender::readData()
{
    SHead head;
    SVehInfo vehQueue;
    SHEADVEH headVeh;
    SResponse response;
    size_t nHeadSize = sizeof head;
    memset(&vehQueue, 0, sizeof vehQueue);
    memset(&response,0, sizeof response);
    //读取全部数据到缓冲区
    m_data += m_socket.readAll();
    //判断当前缓冲区数据是否包含完整的报文
    while(m_data.count() > nHeadSize)
    {
        qMemCopy(&head, m_data.data(), nHeadSize);
        head.toBigEndian();
        if(head.nLength <= m_data.count())
        {
            //根据报文类型，使用不同的方法处理
            switch(head.nType)
            {
            case RESVEH:
                qMemCopy(&response, m_data.data() + sizeof head, sizeof response);
                handleResponse(response);
                break;
            case QUEVEH:
                qMemCopy(&vehQueue, m_data.data() + sizeof head, sizeof vehQueue);
                handleVehQueue(vehQueue);
                break;
            case HEADVEH:
                qMemCopy(&headVeh, m_data.data() + sizeof head, sizeof headVeh);
                handleHeadVeh(headVeh);
                break;
            default:
                break;
            }
            //从缓冲区中移除该报文
            m_data.remove(0, head.nLength);
        }
        else
        {
            break;
        }
    }
}

void MsgSender::handleResponse(SResponse &response)
{
    if(isVaild(m_data.data(), sizeof(SHead) + sizeof(SResponse) - 1, response.nXor))
    {
        response.toBigEndian();
        emit showResponse((RESTYPE)response.nError);
    }
}

void MsgSender::handleVehQueue(SVehInfo &vehInfo)
{
    if(isVaild(m_data.data(), sizeof(SHead) + sizeof(SVehInfo) - 1, vehInfo.nXor))
    {
        emit showVehInfo(vehInfo.vehQueue);
    }
}

void MsgSender::handleHeadVeh(SHEADVEH &headVeh)
{
    if(isVaild(m_data.data(), sizeof(SHead) + sizeof(SHEADVEH) - 1, headVeh.nXor))
    {
        emit showHeadVeh(headVeh.headVeh);
    }
}

bool MsgSender::isVaild(void *buffer, size_t nSize, quint8 nXor)
{
    quint8 tmp = getXor((const char*)buffer, nSize);
    bool ret = tmp == nXor;
    return ret;
}

void MsgSender::modifyVehQueue(PACKETTYPE nType, int nClass)
{
    //封装报文头
    SHead head;
    SControlInfo control;
    head.nType = nType;
    head.nLength = sizeof head + sizeof control;
    head.toBigEndian();
    //封装报文体
    control.nVehType = nClass;
    control.toBigEndian();
    QByteArray tmpData;
    tmpData.append((const char* )&head, sizeof head);
    tmpData.append((const char*)&control, sizeof control -1);
    control.nXOR = getXor(tmpData.data(), tmpData.count());
    tmpData.append((char)control.nXOR);
    //发送数据
    m_socket.write(tmpData);
}
